package com.sykj.seaflow.warm.module.task.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.stream.StreamUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sykj.seaflow.common.base.bean.PageQuery;
import com.sykj.seaflow.common.base.enums.DelFlagEnum;
import com.sykj.seaflow.common.base.util.LoginHelper;
import com.sykj.seaflow.sys.remote.api.SysUserApi;
import com.sykj.seaflow.sys.remote.bean.SysUserBean;
import com.sykj.seaflow.warm.core.bean.FieldSetting;
import com.sykj.seaflow.warm.core.enums.FormFieldPermissionEnum;
import com.sykj.seaflow.warm.core.utils.FlowStatusUtil;
import com.sykj.seaflow.warm.module.instance.entity.SeaFlowUser;
import com.sykj.seaflow.warm.module.instance.service.FlowInstanceService;
import com.sykj.seaflow.warm.module.nodeExt.entity.FlowNodeExt;
import com.sykj.seaflow.warm.module.nodeExt.service.FlowNodeExtService;
import com.sykj.seaflow.warm.module.task.entity.*;
import com.sykj.seaflow.warm.module.task.mapper.SeaFlowTaskMapper;
import com.sykj.seaflow.warm.module.task.params.*;
import com.sykj.seaflow.warm.module.task.service.FlowTaskService;
import lombok.AllArgsConstructor;
import org.dromara.warm.flow.core.dto.FlowParams;
import org.dromara.warm.flow.core.entity.HisTask;
import org.dromara.warm.flow.core.entity.Task;
import org.dromara.warm.flow.core.entity.User;
import org.dromara.warm.flow.core.enums.NodeType;
import org.dromara.warm.flow.core.service.HisTaskService;
import org.dromara.warm.flow.core.service.InsService;
import org.dromara.warm.flow.core.service.TaskService;
import org.dromara.warm.flow.core.service.UserService;
import org.dromara.warm.flow.orm.entity.FlowHisTask;
import org.dromara.warm.flow.orm.entity.FlowTask;
import org.dromara.warm.flow.orm.entity.FlowUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@AllArgsConstructor
@Service
public class FlowTaskServiceImpl implements FlowTaskService {

    private final TaskService taskService;

    private final SeaFlowTaskMapper flowTaskMapper;

    private final SysUserApi   sysUserApi;

    private final HisTaskService hisTaskService;

    private final UserService userService;
//    private final InsService instanceService;

    private final FlowInstanceService flowInstanceService;
    private final InsService instanceService;

    private FlowNodeExtService flowNodeExtService;

//    @Override
//    public IPage<Task> todoPage(FlowTaskQueryParam queryParam, PageQuery<FlowTask> pageQuery) {
//        Page<User> page = new Page<>(pageQuery.getCurrent(), pageQuery.getSize());
//        FlowUser flowUser = new FlowUser();
//        flowUser.setProcessedBy("2");
//        page.setOrderBy("id");
//        Page<User> pageResult = userService.page(flowUser, page);
//        List<Long> list = pageResult.getList().stream().map(User::getAssociated).toList();
//        List<Task> tasks = taskService.getDao().selectByIds(list);
//        // 流程定义
//        List<Long> list1 = tasks.stream().map(Task::getDefinitionId).toList();
//
//        PageDTO<Task> result = new PageDTO<>(pageResult.getPageNum(), pageResult.getPageSize(), pageResult.getTotal());
//        result.setRecords(tasks);
//        return result;
//    }

    // 自定义todo
    @Override
    public IPage<FlowTaskTodo> todoPage(PageQuery<FlowTask> pageQuery, FlowTaskQueryParam flowTaskQueryParam ) {
        QueryWrapper<Object> query = Wrappers.query();
        if(ObjectUtil.isNotEmpty(flowTaskQueryParam.getFlowName())){
            query.like("def.flow_name", flowTaskQueryParam.getFlowName());
        }
        if(ObjectUtil.isNotEmpty(flowTaskQueryParam.getFlowCode())){
            query.like("def.flow_code", flowTaskQueryParam.getFlowCode());
        }
        if(ObjectUtil.isNotEmpty(flowTaskQueryParam.getInitiatorName())){
            query.like("suser.nick", flowTaskQueryParam.getInitiatorName());
        }
        query.eq("fuser.del_flag", DelFlagEnum.NORMAL.getValue());
        query.eq("fuser.processed_by", LoginHelper.getUserIdAsString());
        query.orderByDesc("task.id");
        IPage<FlowTaskTodo> flowTaskTodoIPage = flowTaskMapper.todoPage(pageQuery.getPage(), query);

        // 查询代办人
        List<FlowTaskTodo> records = flowTaskTodoIPage.getRecords();
        if(ObjectUtil.isNotEmpty(records)){

            // 查找 流程 待办人
            flowTodoAssign(records);

//            表单控制处理
            formControl(records);


        }
        flowTaskTodoIPage.getRecords().forEach(r-> {
            String s = flowStatus(r.getInstanceId(), r.getFlowJson());
            r.setFlowJson(s);
        });

        return flowTaskTodoIPage;
    }

    private void formControl(List<FlowTaskTodo> records) {
        records.forEach(r-> {
            String fieldSetting = r.getFieldSetting();
            String formJson = r.getFormJson();
            // json处理
            if(ObjectUtil.isNotEmpty(fieldSetting) && JSONUtil.isTypeJSON(formJson)){
                JSONObject pageSchema = JSONUtil.parseObj(formJson);
                JSONArray jsonArray = pageSchema.getJSONArray("schemas").getJSONObject(0).getJSONArray("children");
                List<FieldSetting> fieldSettingList = JSONUtil.toList(fieldSetting, FieldSetting.class);
                doFormControl(fieldSettingList,jsonArray);
                r.setFormJson(pageSchema.toString());
            }
        });


    }
    private FieldSetting matchFeild(List<FieldSetting> fields, JSONObject field){
        for(FieldSetting f : fields){
            if(ObjectUtil.equal(f.getField(), field.getStr("field"))){
                return f;
            }
        }
        return null;
    }

    private void doFormControl(List<FieldSetting> fieldSettingList, JSONArray jsonArray) {
        for(Object field : jsonArray){
            JSONObject f =  (JSONObject)field;
            if(f.getBool("input")){
                FieldSetting matchFeild = matchFeild(fieldSettingList, f);
                JSONObject componentProps = f.getJSONObject("componentProps");
                if(componentProps == null){
                    componentProps =  new JSONObject();
                    f.set("componentProps",componentProps);
                }
                // 判断是否匹配上
                if( matchFeild != null){
                    FormFieldPermissionEnum permission = FormFieldPermissionEnum.getPermission(matchFeild.getPermission());
                    if(permission != null){
                        if(permission ==  FormFieldPermissionEnum.EDIT ){
                            componentProps.set(FormFieldPermissionEnum.READONLY.getValue(), false);
                            componentProps.set(FormFieldPermissionEnum.HIDDEN.getValue(), false);
                        }
                        componentProps.set(permission.getValue(), true);
                    }else{
                        componentProps.set(FormFieldPermissionEnum.READONLY.getValue(), true);
                    }
                }
            }else{
                JSONArray jsonArray1 = f.getJSONArray("children");
                doFormControl(fieldSettingList, jsonArray1);
            }
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void skip(FlowSkipParam flowSkipParam) {
        String userId = LoginHelper.getUserIdAsString();
        taskService.skip(flowSkipParam.getId(), FlowParams.build().
                // PASS:通过 执行下一个任务 | REJECT:回退 直接结束
                skipType(flowSkipParam.getSkipType()).
                // 设置办理人的权限 ， 就传入当前用户id即可，  所有流程的任务分配在生成任务时 都解析为用户id
                permissionFlag(Arrays.asList(userId)).message(flowSkipParam.getMessage())
                // 指定办理人 和变量
                .handler(userId).variable(flowSkipParam.getVariable())
                .flowStatus(ObjectUtil.isNotEmpty(flowSkipParam.getFlowStatus())? flowSkipParam.getFlowStatus() : null)
                //   ext 和 hisTaskExt 为什么有2个？
                .hisTaskExt(JSONUtil.toJsonStr(flowSkipParam.getVariable())));

    }

    @Override
    public IPage<FlowTaskDone> donePage(PageQuery<FlowTask> pageQuery, FlowDoneTaskQueryParam flowDoneTaskQueryParam) {
        QueryWrapper<Object> query = Wrappers.query();
        query.eq("hist.approver", LoginHelper.getUserIdAsString());
        query.ne("hist.node_type", NodeType.START.getKey());
        if(ObjectUtil.isNotEmpty(flowDoneTaskQueryParam.getFlowName())){
            query.like("def.flow_name", flowDoneTaskQueryParam.getFlowName());
        }
        if(ObjectUtil.isNotEmpty(flowDoneTaskQueryParam.getFlowCode())){
            query.like("def.flow_code", flowDoneTaskQueryParam.getFlowCode());
        }
        IPage<FlowTaskDone> flowTaskDoneIPage = flowTaskMapper.donePage(pageQuery.getPageAndSort(), query);
        List<FlowTaskDone> records = flowTaskDoneIPage.getRecords();
        if(ObjectUtil.isNotEmpty(records)){
            List<Long> list = records.stream().map(FlowTaskDone::getCreateBy).collect(Collectors.toList());//.toList();
            List<Long> list1 = records.stream().map(FlowTaskDone::getApprover).collect(Collectors.toList());//.toList();
            List<Long> userIds = StreamUtil.of(list, list1).flatMap(List::stream).distinct().collect(Collectors.toList());//.toList();
            List<SysUserBean> users = sysUserApi.getUsers(userIds);
            for (FlowTaskDone flowTaskDone : records) {
                users.stream().filter(user -> user.getId().equals(flowTaskDone.getCreateBy())).findFirst().ifPresent(
                        user -> flowTaskDone.setInitiatorName(user.getNick()));
                users.stream().filter(user -> user.getId().equals(flowTaskDone.getApprover())).findFirst().ifPresent(
                        user -> flowTaskDone.setApproverName(user.getNick()));
            }
        }
        flowTaskDoneIPage.getRecords().forEach(r-> {
            String s = flowStatus(r.getInstanceId(), r.getFlowJson());
            r.setFlowJson(s);
        });
        return flowTaskDoneIPage;
    }

    @Override
    public IPage<FlowTaskMy> myPage(PageQuery<FlowTask> pageQuery, FlowMyTaskQueryParam flowMyTaskQueryParam) {
        QueryWrapper<Object> query = Wrappers.query();
        query.eq("inst.create_by", LoginHelper.getUserIdAsString());
        query.orderByDesc("inst.id");
        query.like(ObjectUtil.isNotEmpty(flowMyTaskQueryParam.getFlowCode()), "def.flow_code", flowMyTaskQueryParam.getFlowCode());
        query.like(ObjectUtil.isNotEmpty(flowMyTaskQueryParam.getFlowName()), "def.flow_name", flowMyTaskQueryParam.getFlowName());

        //查询我发起的流程
        IPage<FlowTaskMy> flowTaskDoneIPage = flowTaskMapper.myPage(pageQuery.getPage(), query);
        List<FlowTaskMy> records = flowTaskDoneIPage.getRecords();

        if(ObjectUtil.isNotEmpty(records)){
            List<Long> userIds = records.stream().map(FlowTaskMy::getCreateBy).collect(Collectors.toList());//.toList();
            List<SysUserBean> users = sysUserApi.getUsers(userIds);
            for (FlowTaskMy flowTaskMy : records) {
            // 查询用户名
                users.stream().filter(user -> user.getId().equals(flowTaskMy.getCreateBy())).findFirst().ifPresent(
                        user -> flowTaskMy.setInitiatorName(user.getNick()));
            }
            // 关联正在审批人
            flowMyAssign(records);
        }
        flowTaskDoneIPage.getRecords().forEach(
                r-> {
                    String flowJson = flowStatus(r.getId(), r.getFlowJson());
                    r.setFlowJson(flowJson);

                }
        );
        return flowTaskDoneIPage;
    }

    @Override
    public List<SeaFlowHisTask> hisList(FlowHisTaskQueryParam flowHisTaskQueryParam) {
        HisTask hisTask = new FlowHisTask();
        hisTask.setInstanceId(flowHisTaskQueryParam.getInstId());
        //排序
        List<HisTask> list = hisTaskService.list(hisTask, hisTaskService.orderByDesc("id"));
        List<SeaFlowHisTask> seaflowHisTasks = BeanUtil.copyToList(list, SeaFlowHisTask.class);
        // 获取审批人
        List<Long> userIds = seaflowHisTasks.stream().map(r-> Long.valueOf(r.getApprover())).collect(Collectors.toList());//.toList();
        List<SysUserBean> users = sysUserApi.getUsers(userIds);
        for (SeaFlowHisTask seaflowHisTask : seaflowHisTasks) {
            users.stream().filter(user -> user.getId().equals(Long.valueOf(seaflowHisTask.getApprover()))).findFirst().ifPresent(
                    user -> seaflowHisTask.setApproveName(user.getNick()));
        }
        return seaflowHisTasks;
    }
    @Transactional
    @Override
    public void back(FlowSkipParam flowSkipParam) {
        Long id = flowSkipParam.getId();
        Task task = taskService.getById(id);
        FlowNodeExt flowNodeExt = flowNodeExtService.getOne(Wrappers.<FlowNodeExt>lambdaQuery()
                .eq(FlowNodeExt::getDefId, task.getDefinitionId())
                .eq(FlowNodeExt::getNodeCode, task.getNodeCode()));
//        taskService.
//        查询配置的跳转code
        String userId = LoginHelper.getUserIdAsString();
        taskService.skip(flowSkipParam.getId(), FlowParams.build()
                // PASS:通过 执行下一个任务 | REJECT:回退 直接结束
                .skipType(flowSkipParam.getSkipType())
                .nodeCode(flowNodeExt.getBackTypeNode())
                // 设置办理人的权限 ， 就传入当前用户id即可，  所有流程的任务分配在生成任务时 都解析为用户id
                .permissionFlag(Arrays.asList(userId)).message(flowSkipParam.getMessage())
                // 指定办理人 和变量
                .handler(userId).variable(flowSkipParam.getVariable())
                //   ext 和 hisTaskExt 为什么有2个？
                .hisTaskExt(JSONUtil.toJsonStr(flowSkipParam.getVariable())));
    }

    /**
     * 转办, 默认删除当然办理用户权限，转办后，当前办理不可办理
     *
     * @param flowSkipParam
     */
    @Override
    public void transfer(FlowSkipParam flowSkipParam) {
        taskService.transfer(flowSkipParam.getId(),
                FlowParams.build().handler(LoginHelper.getUserIdAsString())
                        .permissionFlag(Arrays.asList(LoginHelper.getUserIdAsString()))
                        .addHandlers(flowSkipParam.getHandlers().stream().map(String::valueOf).collect(Collectors.toList()))
                        .message(flowSkipParam.getMessage()));
//        taskService.transfer(flowSkipParam.getId(),
//                LoginHelper.getUserIdAsString(),  //办理人
//                Arrays.asList(LoginHelper.getUserIdAsString()),//办理权限
////                List.of(LoginHelper.getUserIdAsString()), // 办理权限
//                flowSkipParam.getHandlers().stream().map(String::valueOf).collect(Collectors.toList()), //.toList(), // 转办人 , Long类型 转string
//                flowSkipParam.getMessage() // 意见
//                );
    }



    //委派, 默认删除当然办理用户权限，转办后，当前办理不可办理
    @Override
    public void depute(FlowSkipParam flowSkipParam) {
        taskService.depute(flowSkipParam.getId(),
                FlowParams.build().handler(LoginHelper.getUserIdAsString())
                        .permissionFlag(Arrays.asList(LoginHelper.getUserIdAsString()))
                        .addHandlers(flowSkipParam.getHandlers().stream().map(String::valueOf).collect(Collectors.toList()))
                        .message(flowSkipParam.getMessage()));
//        taskService.depute(flowSkipParam.getId(),
//                LoginHelper.getUserIdAsString(),
//                Arrays.asList(LoginHelper.getUserIdAsString()),
//                flowSkipParam.getHandlers().stream().map(String::valueOf).collect(Collectors.toList()), //.toList(),
//                flowSkipParam.getMessage()
//        );
    }

    @Override
    public void addSignature(FlowSkipParam flowSkipParam) {
        taskService.addSignature(flowSkipParam.getId(),
                FlowParams.build().handler(LoginHelper.getUserIdAsString())
                        .permissionFlag(Arrays.asList(LoginHelper.getUserIdAsString()))
                        .addHandlers(flowSkipParam.getHandlers().stream().map(String::valueOf).collect(Collectors.toList()))
                        .message(flowSkipParam.getMessage()));
//        taskService.addSignature(flowSkipParam.getId(),
//                LoginHelper.getUserIdAsString(),
//                Arrays.asList(LoginHelper.getUserIdAsString()),
//                flowSkipParam.getHandlers().stream().map(String::valueOf).collect(Collectors.toList()), //.toList(),
//                flowSkipParam.getMessage());
    }

    @Override
    public void reduSignature(FlowSkipParam flowSkipParam) {
        taskService.reductionSignature(flowSkipParam.getId(),
                FlowParams.build().handler(LoginHelper.getUserIdAsString())
                        .permissionFlag(Arrays.asList(LoginHelper.getUserIdAsString()))
                        .addHandlers(flowSkipParam.getHandlers().stream().map(String::valueOf).collect(Collectors.toList()))
                        .message(flowSkipParam.getMessage()));
//        taskService.reductionSignature(flowSkipParam.getId(),
//                LoginHelper.getUserIdAsString(),
//                Arrays.asList(LoginHelper.getUserIdAsString()),
//                flowSkipParam.getHandlers().stream().map(String::valueOf).collect(Collectors.toList()), //.toList(),
//                flowSkipParam.getMessage() );
    }

    @Override
    public List<FlowTaskUser> users(FlowSkipParam FlowSkipParam) {
        Task task = taskService.getById(FlowSkipParam.getId());
        Assert.isTrue(task != null, "任务不存在");
        FlowUser flowUser = new FlowUser();
        flowUser.setAssociated(flowUser.getId());
        List<User> list = userService.list(flowUser);
        if(ObjectUtil.isNotEmpty(list)){
            // 查询用户，
            List<String> userIds = list.stream().map(User::getProcessedBy).collect(Collectors.toList());//.toList();
            List<SysUserBean> users = sysUserApi.getUsers(userIds.stream().map(Long::valueOf).collect(Collectors.toList()));
            List<FlowTaskUser> list1 = users.stream().map(user -> {
//                转为 FlowTaskUser
                FlowTaskUser flowTaskUser = new FlowTaskUser();
                flowTaskUser.setId(user.getId());
                flowTaskUser.setNick(user.getNick());
                return flowTaskUser;
            }).collect(Collectors.toList());//.toList();
            return list1;
        }
        return null;
    }

    @Override
    public List<FlowTaskUser> selectUsers(FlowTaskUserQueryParam flowSkipParam) {
        Task task = taskService.getById(flowSkipParam.getTaskId());
        Assert.isTrue(task != null, "任务不存在");
        FlowUser flowUser = new FlowUser();
        flowUser.setAssociated(flowSkipParam.getTaskId());
        List<User> list = userService.list(flowUser);
        List<String> userIds = list == null  ? null : list.stream().map(User::getProcessedBy).collect(Collectors.toList());//.toList();
        List<SysUserBean> sysUserBeans = sysUserApi.selectUWithOutUsers(userIds);
        if(sysUserBeans == null){
            return null;
        }
        return  BeanUtil.copyToList(sysUserBeans, FlowTaskUser.class);

    }

    @Override
    public String flowStatus(Long instId, String flowJson) {
        // 先获取流程task
        FlowTask flowTask = new FlowTask();
        flowTask.setInstanceId(instId);
        List<Task> taskList = taskService.list(flowTask);
        HisTask hisTask = new FlowHisTask();
        hisTask.setInstanceId(instId);
        List<HisTask> hisTaskList = hisTaskService.list(hisTask);
        return FlowStatusUtil.flowStatus(flowJson, hisTaskList, taskList);
    }

    /**
     *  查询流程待办人
     * @param flowTaskTodos
     */
    private void flowTodoAssign(List<FlowTaskTodo> flowTaskTodos) {
        List<Long> instIds = flowTaskTodos.stream().map(FlowTaskTodo::getInstanceId).collect(Collectors.toList());//.toList();
        // 查询到待办人
        List<SeaFlowUser> seaflowUsers = flowInstanceService.approveList(instIds);
        Map<Long, List<SeaFlowUser>>  instUser = seaflowUsers.stream().collect(Collectors.groupingBy(SeaFlowUser::getInstanceId));

        for(FlowTaskTodo flowTaskTodo: flowTaskTodos){
            List<SeaFlowUser> seaflowUsers1 = instUser.get(flowTaskTodo.getInstanceId());
            flowTaskTodo.setAssigneeList(seaflowUsers1);
        }

    }

    private void flowMyAssign(List<FlowTaskMy> flowTaskMys) {
        List<Long> instIds = flowTaskMys.stream().map(FlowTaskMy::getId).collect(Collectors.toList());//.toList();
        // 查询到待��人
        List<SeaFlowUser> seaflowUsers = flowInstanceService.approveList(instIds);
        Map<Long, List<SeaFlowUser>>  instUser = seaflowUsers.stream().collect(Collectors.groupingBy(SeaFlowUser::getInstanceId));

        for(FlowTaskMy flowTaskMy: flowTaskMys){
            List<SeaFlowUser> seaflowUsers1 = instUser.get(flowTaskMy.getId());
            flowTaskMy.setAssigneeList(seaflowUsers1);
        }

    }

//    public void flowAssign(List<Long> taskIds) {
//        List<User> byAssociateds = userService.getByAssociateds(taskIds);
//
//
//    }
}
